import re
from typing import List, Dict, Any, Tuple
from enum import Enum

class QuestionType(Enum):
    SINGLE_CHOICE = "single_choice"
    MULTIPLE_CHOICE = "multiple_choice"
    MATRIX_SCALE = "matrix_scale"
    OPEN_ENDED = "open_ended"

class QuestionParser:
    """问题解析器，支持多种题型"""
    
    @staticmethod
    def parse_question(text: str) -> Dict[str, Any]:
        """解析问题文本，识别题型"""
        text = text.strip()
        
        # 检测单选题
        single_choice_match = re.search(r'(?:（|\[)?单选题(?:）|\])?[：:：]?\s*(?:[A-Da-d1-4][、．.．\s])?', text)
        if single_choice_match:
            return QuestionParser._parse_single_choice(text)

        # 检测多选题
        multiple_choice_match = re.search(r'(?:（|\[)?多选题(?:）|\])?[：:：]?\s*(?:[A-Da-d1-4][、．.．\s])?', text)
        if multiple_choice_match:
            return QuestionParser._parse_multiple_choice(text)

        # 检测矩阵量表题
        matrix_match = re.search(r'矩阵|量表|评分表|打分', text)
        if matrix_match:
            return QuestionParser._parse_matrix_scale(text)

# 默认作为开放题

        
        # 默认作为开放题
        return QuestionParser._parse_open_ended(text)
    
    @staticmethod
    def _parse_single_choice(text: str) -> Dict[str, Any]:
        """
        解析单选题，支持 "A./B." 和 "○" 两种选项格式。
        """
        lines = text.split('\n')
        question_text = ""
        options: List[Dict[str, str]] = []
        
        # 标记是否已经开始解析选项
        found_options_started = False
        
        # 用于自动生成 A, B, C...
        option_key_counter = 0 
        
        # --- 正则表达式 ---
        
        # 1. 匹配 A/B/C/D 格式的选项
        #    ^([A-Da-d])      -> 捕获 A, B, C, D (不区分大小写)
        #    [、．.．\s]        -> 匹配各种分隔符（顿号、点、空格）
        #    \s*(.+)$         -> 捕获选项内容
        re_key_option = re.compile(r'^([A-Da-d])[、．.．\s]\s*(.+)$')
        
        # 2. 匹配 ○ 格式的选项
        #    ^[○oO]           -> 匹配 '○' 或 'o'/'O' (以防输入错误)
        #    \s*(.+)$         -> 捕获选项内容
        re_symbol_option = re.compile(r'^[○oO]\s*(.+)$')

        # 3. 匹配行首的题号（如 "1." "2、"），用于从题干中剥离
        #    ^\d+             -> 匹配一个或多个数字
        #    [、．.．\s]        -> 匹配分隔符
        re_question_num = re.compile(r'^\d+[、．.．\s]')

        
        for line in lines:
            line = line.strip()
            if not line:
                continue
                
            # 尝试匹配两种选项格式
            match_key = re_key_option.match(line)
            match_symbol = re_symbol_option.match(line)
            
            if match_key:
                # --- 匹配到 "A. 选项" 格式 ---
                found_options_started = True
                option_key = match_key.group(1).upper()
                option_text = match_key.group(2).strip()
                options.append({"key": option_key, "text": option_text})
                
            elif match_symbol:
                # --- 匹配到 "○ 选项" 格式 ---
                found_options_started = True
                # 自动生成 A, B, C...
                option_key = chr(ord('A') + option_key_counter)
                option_text = match_symbol.group(1).strip()
                options.append({"key": option_key, "text": option_text})
                option_key_counter += 1
                
            elif not found_options_started:
                # --- 尚未开始解析选项，此行为题干 ---
                
                # 检查并去除行首的 "2. " 这样的题号
                match_num = re_question_num.match(line)
                if match_num:
                    # 只保留题号后面的内容
                    question_text += line[match_num.end():].strip() + " "
                else:
                    # 没有题号，整行都是题干
                    question_text += line + " "
            
            # else:
                # 如果 found_options_started 为 True，但又没匹配上任何选项
                # 这可能是一个多行选项，或者是一个格式错误的行。
                # 当前逻辑选择忽略它，您可以根据需要修改。
                # pass 

        return {
            "type": QuestionType.SINGLE_CHOICE, # 恢复使用您的枚举
            "text": question_text.strip(),
            "options": options
        }
    @staticmethod
    def _parse_multiple_choice(text: str) -> Dict[str, Any]:
        """解析多选题"""
        lines = text.split('\n')
        question_text = ""
        options = []
        option_key_counter = 0
        for line in lines:
            line = line.strip()
            if not line:
                continue
                
            # 匹配选项格式
            re_symbol_option = re.compile(r'^[○oO□]\s*(.+)$')
            match_symbol = re_symbol_option.match(line)
            if match_symbol:
                option_key = chr(ord('A') + option_key_counter)
                option_text = match_symbol.group(1).strip()
                options.append({"key": option_key, "text": option_text})
                option_key_counter += 1
            elif not options and line:
                question_text += line + " "
        
        return {
            "type": QuestionType.MULTIPLE_CHOICE,
            "text": question_text.strip(),
            "options": options
        }
    
    @staticmethod
    def _parse_matrix_scale(text: str) -> Dict[str, Any]:
        """解析矩阵量表题"""
        lines = text.split('\n')
        question_text = ""
        statements = []
        scale_labels = []
        SCALE_KEYWORDS = ["非常", "很", "一般", "需要", "不需要", "满意", "不满意", "重要", "不重要", "喜欢", "不喜欢"]

        for line in lines:
            line = line.strip()
            if not line:
                continue
            
            # 检测量表标签（如：非常不同意、不同意、一般、同意、非常同意）
            # 检查这一行是否包含量表关键词
            if any(word in line for word in SCALE_KEYWORDS) and not statements:
                # 将这一行按空格或tab拆分为量表选项
                scale_labels = [item.strip() for item in re.split(r'\s+', line) if any(k in item for k in SCALE_KEYWORDS)]
                continue
            # # 如果已经识别了量表标签，则后续行都是量表条目
            # if scale_labels:
            #     statements.append(line)
            # 检测陈述句（矩阵行）
            elif line.split('\t')[0] and "○" in line:
                statement = QuestionParser._extract_statement(line)
                if statement:
                    statements.append(statement)
            elif not statements and line:
                question_text += line + " "
        
        # 如果没有检测到明确的量表标签，使用默认标签
        if not scale_labels:
            scale_labels = [
                "非常不同意", "不同意", "一般", "同意", "非常同意"
            ]
        
        return {
            "type": QuestionType.MATRIX_SCALE,
            "text": question_text.strip(),
            "statements": statements,
            "scale_labels": scale_labels
        }
    
    @staticmethod
    def _parse_open_ended(text: str) -> Dict[str, Any]:
        """解析开放题"""
        return {
            "type": QuestionType.OPEN_ENDED,
            "text": text.strip()
        }
    
    @staticmethod
    def _extract_scale_labels(line: str) -> List[str]:
        """提取量表标签"""
        # 常见的量表标签模式
        patterns = [
            r'[非常很]?不同意|[非常很]?同意',
            r'[非常很]?不满意|[非常很]?满意',
            r'[非常很]?不重要|[非常很]?重要',
            r'[非常很]?不喜欢|[非常很]?喜欢'
        ]
        
        labels = []
        words = re.split(r'[,\s、；;]', line)
        
        for word in words:
            word = word.strip()
            if any(re.search(pattern, word) for pattern in patterns):
                labels.append(word)
        
        return labels if labels else []
    
    @staticmethod
    def _extract_statement(line: str) -> str:
        """提取陈述句"""
        # 去除序号和标点
        statement = line.split('\t')[0]
        return statement.strip()

class ResponseGenerator:
    """回答生成器，根据题型生成合适的回答"""
    
    @staticmethod
    def generate_response(question: Dict[str, Any], agent_profile: Dict[str, str]) -> str:
        """根据问题类型生成回答"""
        question_type = question["type"]
        
        if question_type == QuestionType.SINGLE_CHOICE:
            return ResponseGenerator._generate_single_choice_response(question, agent_profile)
        elif question_type == QuestionType.MULTIPLE_CHOICE:
            return ResponseGenerator._generate_multiple_choice_response(question, agent_profile)
        elif question_type == QuestionType.MATRIX_SCALE:
            return ResponseGenerator._generate_matrix_scale_response(question, agent_profile)
        else:
            return ResponseGenerator._generate_open_ended_response(question, agent_profile)
    
    @staticmethod
    def _generate_single_choice_response(question: Dict[str, Any], agent_profile: Dict[str, str]) -> str:
        """生成单选题回答"""
        prompt = f"""请作为{agent_profile['background']}，性格{agent_profile['personality']}的人回答以下单选题：

问题：{question['text']}

选项：
{ResponseGenerator._format_options(question['options'])}

请选择最符合您背景和性格的一个选项，并简要说明选择理由。"""

        return prompt
    
    @staticmethod
    def _generate_multiple_choice_response(question: Dict[str, Any], agent_profile: Dict[str, str]) -> str:
        """生成多选题回答"""
        prompt = f"""请作为{agent_profile['background']}，性格{agent_profile['personality']}的人回答以下多选题：

问题：{question['text']}

选项：
{ResponseGenerator._format_options(question['options'])}

请选择所有符合您背景和性格的选项（可以多选），并简要说明选择理由。"""

        return prompt
    
    @staticmethod
    def _generate_matrix_scale_response(question: Dict[str, Any], agent_profile: Dict[str, str]) -> str:
        """生成矩阵量表题回答"""
        scale_labels = " → ".join(question['scale_labels'])
        
        prompt = f"""请作为{agent_profile['background']}，性格{agent_profile['personality']}的人回答以下矩阵量表题：

问题：{question['text']}

量表程度：{scale_labels}

请对以下陈述进行评分：
{ResponseGenerator._format_statements(question['statements'])}

请为每个陈述选择最符合您观点的评分，并保持回答的一致性。"""

        return prompt
    
    @staticmethod
    def _generate_open_ended_response(question: Dict[str, Any], agent_profile: Dict[str, str]) -> str:
        """生成开放题回答"""
        prompt = f"""请作为{agent_profile['background']}，性格{agent_profile['personality']}的人回答以下开放题：

问题：{question['text']}

请给出详细、真实的回答，充分体现您的背景和性格特点。"""

        return prompt
    
    @staticmethod
    def _format_options(options: List[Dict[str, str]]) -> str:
        """格式化选项"""
        return "\n".join([f"{opt['key']}. {opt['text']}" for opt in options])
    
    @staticmethod
    def _format_statements(statements: List[str]) -> str:
        """格式化陈述句"""
        return "\n".join([f"{i+1}. {stmt}" for i, stmt in enumerate(statements)])